// ==================================================================================
// Shared Genomics Project MPI Codebase
// Version 1.0 30/04/2010
//
// (c) 2010 University of Manchester all rights reserved
//
// This file is distributed under the GNU General Public License, Version 2.  
// Please see the file COPYING.txt for more details
// ==================================================================================

/*!
\file
\brief	Implementation of SNP 2-way interaction */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "_int2.h"
#include "types.h"
#include "utils.h"

#ifndef MAX_LINE_LENGTH
#define MAX_LINE_LENGTH 1024
#endif

#define MAX_INT2_ARRAY_SIZE 100000

void int2_init(struct INT2 *i) {
	if (i != NULL) {
		i->nPermutations = i->maxR = i->R = i->p1 = i->p2 = 0;
		i->coeff = i->z = 0;
		i->valid = FALSE;
	}
}

// QSORT comparator function.
int int2_cmp(const void* p1, const void* p2) {
	const struct INT2 *a = (const struct INT2*) p1;
	const struct INT2 *b = (const struct INT2*) p2;

	if (a == NULL || b == NULL) return 0;

	if (a->p1 < b->p1) return -1;
	else if (a->p1 > b->p1) return 1;
	else if (a->p1 == b->p1) {
		if (a->p2 < b->p2) return -1;
		else if (a->p2 > b->p2) return 1;
		else if (a->p2 == b->p2) return 0;
	}

	return  0;
}

// Echo value of INT2 to STDOUT
void int2_echo(struct INT2 *i2) {
	if (i2 != NULL) fprintf(stdout, "p1=%i, p2=%i, z=%f, coeff=%f, nperm=%i, R=%i, maxR=%i\n", i2->p1, i2->p2, i2->z, i2->coeff, i2->nPermutations, i2->R, i2->maxR);
}

struct INT2* int2_load(char *filepath, int *nNumberRead) {
	FILE *in = NULL;
	struct INT2 *values = NULL;

	*nNumberRead  = 0;

	in = fopen(filepath, "rb");
	if (in != NULL) {
		if(fread(nNumberRead, sizeof(int), 1, in) == 1) {
			if (*nNumberRead > 0) {
				values = (struct INT2*) malloc(sizeof(struct INT2) * (*nNumberRead));
				if (values != NULL) {
					if (fread(values, sizeof(struct INT2), *nNumberRead, in) != *nNumberRead) {
						free(values);
						nNumberRead  = 0;
					} 
				}
			}
		}
		fclose(in);
	}

	return values;
}

int int2_search(struct INT2 *a, int nA, struct INT2 *x)
{
	if (a != NULL && nA > 0) {
		int l, r, c;
		for (l = 0, r = nA-1; l <= r;) {
			c = l+(r-l) / 2;
			if (int2_cmp(&a[c], x) == 1) // greater than
				r = c - 1;
			else if (int2_cmp(&a[c], x) == -1) // less than
				l = c + 1;
			else
				return c;
		}
	}

	return -1;
}

void int2_reset_valid(struct INT2 *a, int nA) {
	if (a != NULL && nA > 0) {
		int i;
		for (i = 0; i < nA; i++) a[i].valid = FALSE;
	}
}
